using System;
using Microsoft.SPOT;

namespace Microsoft.Xna.Framework
{
    public struct Rectangle
    {
        public bool HasValue { get; private set; }
        public int X { get; set; }
        public int Y { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }

        public int Bottom
        {
            get { return Y + Height; }
        }

        public Point Center
        {
            get { return new Point(X + Width / 2, Y + Height / 2); }
        }

        public static Rectangle Empty
        {
            get { return new Rectangle() { HasValue = true }; }
        }

        public static Rectangle Null
        {
            get { return new Rectangle() { HasValue=false }; }
        }

        public int Left
        {
            get { return X; }
        }

        public int Right
        {
            get { return X + Width; }
        }

        public int Top
        {
            get { return Y; }
        }

        public Rectangle(int x, int y, int width, int height)
            : this()
        {
            this.X = x;
            this.Y = y;
            this.Width = width;
            this.Height = height;
            this.HasValue = true;
        }

        public bool Contains(int x, int y)
        {
            return x >= X && y >= Y && x < X + Width && y < Y + Height;
        }

        public bool Contains(Point value)
        {
            return value.X >= X && value.Y >= Y && value.X < X + Width && value.Y < Y + Height;
        }

        public void Contains(ref Point value, out bool result)
        {
            result = Contains(value);
        }

        public bool Contains(Rectangle value)
        {
            return value.X >= X && value.Y >= Y && value.X + Width <= X + Width && value.Y + value.Height <= Y + Height;
        }

        public void Contains(ref Rectangle value, out bool result)
        {
            result = value.X >= X && value.Y >= Y && value.X + Width <= X + Width && value.Y + value.Height <= Y + Height;
        }

        public bool Equals(Rectangle value)
        {
            return X == value.X && Y == value.Y && Width == value.Width && Height == value.Height;
        }

        public override bool Equals(object obj)
        {
            if (obj is Rectangle)
            {
                return Equals((Rectangle)obj);
            }
            return false;
        }

        public override int GetHashCode()
        {
            return X.GetHashCode() + Y.GetHashCode() + Width.GetHashCode() + Height.GetHashCode();
        }

        public void Inflate(int horizontalAmount, int verticalAmount)
        {
            X -= horizontalAmount;
            Y -= verticalAmount;
            Width += horizontalAmount;
            Height += verticalAmount;
        }

        public bool Intersects(Rectangle value)
        {
            return value.X < X + Width && X < value.X + value.Width && value.Y < Y + Height && Y < value.Y + value.Height;
        }

        public void Intersects(ref Rectangle value, out bool result)
        {
            result = value.X < X + Width && X < value.X + value.Width && value.Y < Y + Height && Y < value.Y + value.Height;
        }

        public void Offset(int offsetX, int offsetY)
        {
            X += offsetX;
            Y += offsetY;
        }

        public void Offset(Point offset)
        {
            X = (int)(X + offset.X);
            Y = (int)(Y + offset.Y);
        }

        public static bool operator ==(Rectangle a, Rectangle b)
        {
            return a.X == b.X && a.Y == b.Y && a.Width == b.Width && a.Height == b.Height;
        }

        public static bool operator !=(Rectangle a, Rectangle b)
        {
            return a.X != b.X || a.Y != b.Y || a.Width != b.Width || a.Height != b.Height;
        }

        public override string ToString()
        {
            return string.Concat("{", X.ToString(), " Y:", Y.ToString(), 
                " Width:", Width.ToString(), " Height:", Height.ToString(), "}");
        }
    }
}
